import dispatch
import turbogears.validators as tg_validators
from formencode.schema import Schema as fcSchema
from formencode.api import Invalid

from mnemoply._renewed_model import field
from mnemoply._renewed_utils import PhoneFormat
from mnemoply.model import field as field_old
from mnemoply.widgets import PhoneSchema as PhoneSchema1

formencode_validators = tg_validators.validators
Bool=formencode_validators.Bool()

class AutoCompleteSchema(fcSchema ):
    allow_extra_fields = False
    if_key_missing = None
    
    
class Schema(fcSchema):
    allow_extra_fields = True
    if_key_missing = None

class EmptyStringConverter(formencode_validators.FancyValidator):
    """
    Converts empty string to None value. Doesn't change any other values.
    """
    def _to_python(self, value, state):
        if isinstance(value, basestring) and len(value) == 0:
            return None
        else:
            return value
        

class IdsValidator(formencode_validators.FancyValidator):
    not_empty = True
    messages = {
        'idlist': "Please enter id list (values separated by comma)",
    }

    def _to_python(self, value, state):
        try:
            assert isinstance(value, types.StringTypes)
            return [int(x) for x in value.split(',')]
        except (AssertionError, ValueError, TypeError):
            raise formencode_validators.Invalid(self.message('idlist', state),
                          value, state)

    def _from_python(self, value, state):
        assert isinstance(value, types.ListType)
        return ','.join([str(int(x)) for x in value])


class AutoCompleteFieldValidator(formencode_validators.FancyValidator):
    """
        Validator for AutoCompleteField.
    """
    model_object = None
    def __init__(self, model_object=None, not_empty=False, *args, **kw):
        kw['model_object'] = model_object
        self.model_object = model_object
        super(formencode_validators.FancyValidator, self).__init__(*args, **kw)

    messages = {
        'Incorrectly dialed': "Incorrectly dialed",  #TODO
        }
    def _to_python(self, value, state):
        if isinstance(value,dict):
            res = value["hidden"]
        else:
            res = dict(hidden=str(value), text=self.model_object.get(value).title)
        return res
        
    def _from_python(self, value, state):
        return self.to_python(value, state)   

 
class PhoneMainFieldValidator(formencode_validators.FancyValidator):
    """
    """
    messages = {
        'Incorrectly dialed': "Incorrectly dialed", 
        }
    not_empty = True        
    def _to_python(self, value, state):
        if isinstance(value,dict):
            res = PhoneFormat.dict_to_str(value)
        else:
            res = PhoneFormat.str_to_dict(value)
        if res == PhoneFormat.bad_str():
            raise Invalid(self.message('Incorrectly dialed', state), value, state)
        return res
        
    def _from_python(self, value, state):
        return self.to_python(value, state)       

class PhoneMainSchema(Schema):
    """
        Validation schema which intakes Phone 
    """
    allow_extra_fields = False
    if_key_missing = None
    chained_validators  = [PhoneMainFieldValidator()]

class EqualAccountFromTwoPersonalities(formencode_validators.FancyValidator):
    
    messages = {
    'invalidNoMatch':'Plan' #TODO
        }
    field_names = None
    __unpackargs__ = ('*', 'field_names')
    def validate_python(self, field_dict, state):
        ref1 = field_dict[self.field_names[0]]
        ref1= field.Personality.get(ref1).account
        ref2 = field_dict[self.field_names[1]]
        ref2= field.Personality.get(ref2).account
        error_message = ''
        if ref1 != ref2:
            error_message = self.message('invalidNoMatch', state)
        if error_message:
            raise Invalid(error_message,
                          field_dict, state,
                          error_dict={self.field_names[0]:error_message})

class NoSamePlan(formencode_validators.FancyValidator):
    messages = {
    'invalidNoMatch':"Plan" #TODO
        }
    field_names = None
    __unpackargs__ = ('*', 'field_names')
    def validate_python(self, field_dict, state):
        group = field_dict[self.field_names[0]]
        student = field_dict[self.field_names[1]]
        plan = field_old.Group.get(group).initialPlan
        agrs= field.EducationAgreement.selectBy(student=student)
        plans = [agr.group.initialPlan for agr in agrs  if agr.group.initialPlan==plan and group!=agr.group.id]
        error_message = ''
        if plans:
            error_message = self.message('invalidNoMatch', state)
        if error_message:
            raise Invalid(error_message,
                          field_dict, state,
                          error_dict={self.field_names[0]:error_message})

class PreferedDayFieldValidator(formencode_validators.FancyValidator):
    

    def _to_python(self, value, state):
        try:
            if value is None:
                return '::::::'

            assert isinstance(value, dict)
            vals = []
            for d in range(1, 8):
                part = value[str(d)]
                vals.append((part is not None) and str(int(part)) or '')

            return ':'.join(vals)
        except (AssertionError, ValueError, TypeError):
            raise formencode.Invalid('Internal error in PreferedDayFieldValidator', value, state)

    def _from_python(self, value, state):
        if value is None:
            return dict([(str(x), None) for x in range(1, 7)])

        value = value.split(':')
        assert len(value) == 7

        result = {}
        for number, x in enumerate(value):
            result[str(number + 1)] = (x != '') and int(x) or None
        return result

class PreferedDaySchema(Schema):

    allow_extra_fields = False
    if_key_missing = None
